home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 11: TSX-11 / Linux Cubed Series 11 - TSX-11 Vol 1.iso / sbin / bootutil.1 / bootutil / bootutils / mount / umount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-01  |  5.0 KB  |  206 lines

  1. /*
  2.  * A umount(8) for Linux 0.97.
  3.  * $Header: /usr/src/mount/RCS/umount.c,v 1.1 1992/09/06 13:30:53 root Exp root $
  4.  */
  5.  
  6. #include "sundries.h"
  7.  
  8.  
  9. char *usage = "\
  10. Usage: umount [-av] [-t vfstypes]
  11.        umount [-v] special | node";
  12.  
  13. #ifdef notyet
  14. /* Nonzero for force mount (-f).  This needs kernel support we don't have.  */
  15. int force = 0;
  16. #endif
  17.  
  18. /* Nonzero for chatty (-v).  This is a nonstandard flag (not in BSD).  */
  19. int verbose = 0;
  20.  
  21.  
  22. /* Update the locked mtab by removing any SPECIAL entries and unlocking it.  */
  23. static void
  24. update_mtab (const char *special)
  25. {
  26.   struct mntent *mnt;
  27.  
  28.   open_mtab ("r");
  29.  
  30.   while ((mnt = getmntent (F_mtab)))
  31.     if (!streq (mnt->mnt_fsname, special))
  32.       if (addmntent(F_lock, mnt) == 1)
  33.     die (1, "umount: error writing %s: %s",
  34.          MOUNTED_LOCK, strerror (errno));
  35.  
  36.   endmntent (F_mtab);
  37.   if (fchmod (fileno (F_lock), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
  38.     die (1, "umount: error changing mode of %s: %s",
  39.     MOUNTED_LOCK, strerror (errno));
  40.   endmntent (F_lock);
  41.  
  42.   if (rename (MOUNTED_LOCK, MOUNTED) < 0)
  43.     die (1, "umount: can't rename %s to %s: %s",
  44.      MOUNTED_LOCK, MOUNTED, strerror(errno));
  45. }
  46.  
  47. /* Umount a single device.  Return a status code, so don't exit
  48.    on a non-fatal error.  We lock/unlock around each umount.  */
  49. static int
  50. umount_one (const char *spec, const char *node)
  51. {
  52.   const char *what;
  53.   int umnt_err;
  54.   int isroot;
  55.  
  56.   /* Special case for root.  As of 0.99pl10 we can (almost) unmount root;
  57.      the kernel will remount it readonly so that we can carry on running
  58.      afterwards.  The readonly remount is illegal if any files are opened
  59.      for writing at the time, so we can't update mtab for an unmount of
  60.      root.  As it is only really a remount, this doesn't matter too
  61.      much.  [sct May 29, 1993] */
  62.   isroot = (streq (node, "/") || streq (node, "root"));
  63.  
  64.   what = (*spec == '/') ? spec : node;
  65.   if (!isroot)
  66.       lock_mtab ();
  67.  
  68.   if (umount (what) >= 0)
  69.     /* Umount succeeded, update mtab.  */
  70.     {
  71.       if (verbose)
  72.     printf ("%s umounted\n", spec);
  73.       
  74.       if (!isroot)
  75.           update_mtab (spec);
  76.       return 0;
  77.     }
  78.  
  79.   /* Umount failed, complain, but don't die.  */
  80.   umnt_err = errno;
  81.   if (!isroot)
  82.       unlock_mtab ();
  83.  
  84.   switch (umnt_err)
  85.     {
  86.     case ENXIO:   error ("umount: %s: invalid block device", spec); break;
  87.     case EINVAL:  error ("umount: %s: not mounted", spec); break;
  88.     case EIO:     error ("umount: %s: can't write superblock", spec); break;
  89.     case EBUSY:   error ("umount: %s: device is busy", spec); break;
  90.     case ENOENT:  error ("umount: %s: not mounted", spec); break;
  91.     case EPERM:   error ("umount: %s: must be superuser to umount", spec); break;
  92.     case EACCES:  error ("umount: %s: block devices not permitted on fs", spec); break;
  93.     default:      error ("umount: %s: %s", spec, strerror (umnt_err)); break;
  94.     }
  95.   return 1;
  96. }
  97.  
  98. /* Unmount all filesystems of type VFSTYPES found in mtab.  Since we are
  99.    concurrently updating mtab after every succesful umount, we have to
  100.    slurp in the entire file before we start.  This isn't too bad, because
  101.    in any case it's important to umount mtab entries in reverse order
  102.    to umount, e.g. /usr/spool before /usr.  */
  103. static int
  104. umount_all (string_list types)
  105. {
  106.   string_list spec_list = NULL;
  107.   string_list node_list = NULL;
  108.   struct mntent *mnt;
  109.   int errors;
  110.  
  111.   open_mtab ("r");
  112.  
  113.   while ((mnt = getmntent (F_mtab)))
  114.     if (matching_type (mnt->mnt_type, types))
  115.       {
  116.     spec_list = cons (xstrdup (mnt->mnt_fsname), spec_list);
  117.     node_list = cons (xstrdup (mnt->mnt_dir), node_list);
  118.       }
  119.  
  120.   close_mtab ();
  121.  
  122.   errors = 0;
  123.   while (spec_list != NULL)
  124.     {
  125.       errors |= umount_one (car (spec_list), car (node_list));
  126.       spec_list = cdr (spec_list);
  127.       node_list = cdr (node_list);
  128.     }
  129.  
  130.   sync();
  131.   return errors;
  132. }
  133.  
  134. /* Given the name FILE, try to find it in mtab.  */ 
  135. static struct mntent *
  136. getmntfile (const char *file)
  137. {
  138.   struct mntent *mnt;
  139.  
  140.   open_mtab ("r");
  141.  
  142.   while ((mnt = getmntent (F_mtab)) != NULL)
  143.     {
  144.       if (streq (mnt->mnt_dir, file))
  145.     break;
  146.       if (streq (mnt->mnt_fsname, file))
  147.     break;
  148.     }
  149.  
  150.   close_mtab ();
  151.  
  152.   return mnt;
  153. }
  154.  
  155. int
  156. main (int argc, char **argv)
  157. {
  158.   int opt;
  159.   int all = 0;
  160.   string_list types = NULL;
  161.   struct mntent *fs;
  162.   char *file;
  163.  
  164.   while ((opt = getopt (argc, argv, "aft:v")) != EOF)
  165.     switch (opt)
  166.       {
  167.       case 'a':            /* umount everything */
  168.     ++all;
  169.     break;
  170. #ifdef notyet
  171.       case 'f':            /* force umount (needs kernel support) */
  172.     ++force;
  173.     break;
  174. #endif
  175.       case 't':            /* specify file system type */
  176.     types = parse_types (optarg);
  177.     break;
  178. #ifdef notyet
  179.       case 'u':            /* change mount flags (update a mounted fs) */
  180.     ++update;
  181.     break;
  182. #endif
  183.       case 'v':            /* make noise */
  184.     ++verbose;
  185.     break;
  186.       default:
  187.     die (2, usage);
  188.       }
  189.  
  190.   argc -= optind;
  191.   argv += optind;
  192.  
  193.   if (all)
  194.     return umount_all (types);
  195.  
  196.   if (argc != 1)
  197.     die (2, usage);
  198.  
  199.   file = canonicalize (*argv); /* mtab paths are canonicalized */
  200.  
  201.   if ((fs = getmntfile (file)) != NULL)
  202.     return umount_one (xstrdup (fs->mnt_fsname), xstrdup(fs->mnt_dir));
  203.  
  204.   return umount_one (*argv, NULL);
  205. }
  206.